package com.ruoyi.huanjing.tool;

import com.ruoyi.huanjing.entity.DataBlock;
import com.ruoyi.huanjing.entity.DistancePulseData;
import com.ruoyi.huanjing.entity.TimeDopplerSpectrum;
import com.ruoyi.huanjing.entity.dto.*;
import org.knowm.xchart.*;
import org.knowm.xchart.style.Styler;

import java.io.*;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.*;

/**
 * 电磁特性数据解析工具类（优化版）
 * 修复数据块定位问题，支持按类型准确定位解析
 */
public class ElectromagneticDataTool {

    // 数据块顺序枚举（与文件中存储顺序完全一致）
    private enum BlockOrder {
        AVERAGE_SCATTERING,  // 1. 平均散射系数
        TIME_VARYING_SCATTERING,  // 2. 时变散射系数
        AMPLITUDE_PDF,  // 3. 幅度概率密度
        TIME_CORRELATION,  // 4. 时间相关特性
        DISTANCE_CORRELATION,  // 5. 距离相关特性
        DOPPLER_SPECTRUM,  // 6. 多普勒谱
        IMAGE_1D,  // 7. 一维图像
        DISTANCE_PULSE,  // 8. 距离-脉冲
        TIME_DOPPLER  // 9. 时变多普勒谱
    }

    // 可视化类型枚举（与数据块顺序对应）
    public enum VisualizeType {
        AVERAGE_SCATTERING,  // 平均散射系数
        TIME_VARYING_SCATTERING,  // 时变散射系数
        AMPLITUDE_PDF,  // 幅度概率密度
        TIME_CORRELATION,  // 时间相关特性
        DISTANCE_CORRELATION,  // 距离相关特性
        DOPPLER_SPECTRUM,  // 多普勒谱
        IMAGE_1D,  // 一维图像
        DISTANCE_PULSE,  // 距离-脉冲数据
        TIME_DOPPLER  // 时变多普勒谱
    }

    // 文件路径
    private final String filePath;
    // 文件字节数据
    private byte[] fileData;
    // 字节序（默认小端）
    private ByteOrder byteOrder = ByteOrder.LITTLE_ENDIAN;
    // 解析结果
    private ParseResult parseResult;

    public ElectromagneticDataTool(String filePath) {
        this.filePath = filePath;
    }

    public void setByteOrder(ByteOrder byteOrder) {
        this.byteOrder = byteOrder;
    }

        /**
     * 读取指定路径的文件内容到内存中
     *
     * @return boolean 读取成功返回true，读取失败返回false
     */
    public boolean readFile() {
        File file = new File(filePath);
        if (!file.exists()) {
            System.err.println("文件不存在: " + filePath);
            return false;
        }

        // 使用FileInputStream和ByteArrayOutputStream读取文件内容
        try (FileInputStream fis = new FileInputStream(file);
             ByteArrayOutputStream bos = new ByteArrayOutputStream()) {

            byte[] buffer = new byte[8192];
            int bytesRead;
            // 循环读取文件数据到缓冲区，然后写入字节数组输出流
            while ((bytesRead = fis.read(buffer)) != -1) {
                bos.write(buffer, 0, bytesRead);
            }
            fileData = bos.toByteArray();
            System.out.printf("文件读取成功，大小: %d 字节%n", fileData.length);
            return true;

        } catch (IOException e) {
            System.err.println("文件读取失败: " + e.getMessage());
            return false;
        }
    }


    /**
     * 检测文件数据的字节序
     *
     * @return 检测到的字节序，如果检测失败或数据不足则返回默认的小端序
     */
    public ByteOrder detectByteOrder() {
        // 检查文件数据是否有效
        if (fileData == null || fileData.length < 4) {
            System.err.println("文件数据为空或长度不足，使用默认小端序");
            return ByteOrder.LITTLE_ENDIAN;
        }

        // 分别以小端序和大端序读取前4个字节
        ByteBuffer buffer = ByteBuffer.wrap(fileData);
        int le = buffer.order(ByteOrder.LITTLE_ENDIAN).getInt();
        int be = buffer.order(ByteOrder.BIG_ENDIAN).getInt();

        // 验证读取的值是否合理（正数且不超过文件长度）
        boolean leValid = le > 0 && le * 8L <= fileData.length;
        boolean beValid = be > 0 && be * 8L <= fileData.length;

        // 根据验证结果确定字节序
        if (leValid && !beValid) {
            return ByteOrder.LITTLE_ENDIAN;
        } else if (!leValid && beValid) {
            return ByteOrder.BIG_ENDIAN;
        } else {
            System.out.println("字节序检测模糊，使用默认小端序");
            return ByteOrder.LITTLE_ENDIAN;
        }
    }


    /**
     * 解析文件数据
     *
     * @param visualize 是否进行可视化处理
     * @param type      指定要解析和可视化的数据块类型
     * @return 解析结果对象，包含解析出的数据；如果解析失败则返回 null
     */
    public ParseResult parse(boolean visualize, VisualizeType type) {
        if (!readFile()) {
            return null;
        }

        this.byteOrder = detectByteOrder();
        System.out.println("使用字节序: " + (byteOrder == ByteOrder.LITTLE_ENDIAN ? "小端" : "大端"));

        ByteBuffer buffer = ByteBuffer.wrap(fileData).order(byteOrder);
        parseResult = new ParseResult();

        try {
            // 将VisualizeType转换为对应的BlockOrder，确定数据块在文件中的顺序
            BlockOrder targetBlock = BlockOrder.valueOf(type.name());

            // 跳过目标数据块之前的所有数据块，定位到目标块起始位置
            skipBlocksBeforeTarget(buffer, targetBlock);

            // 根据目标数据块类型解析对应的数据内容
            switch (targetBlock) {
                case AVERAGE_SCATTERING:
                    parseDataBlock(buffer, "平均散射系数");
                    break;
                case TIME_VARYING_SCATTERING:
                    parseDataBlock(buffer, "时变散射系数");
                    break;
                case AMPLITUDE_PDF:
                    parseDataBlock(buffer, "幅度概率密度");
                    break;
                case TIME_CORRELATION:
                    parseDataBlock(buffer, "时间相关特性");
                    break;
                case DISTANCE_CORRELATION:
                    parseDataBlock(buffer, "距离相关特性");
                    break;
                case DOPPLER_SPECTRUM:
                    parseDataBlock(buffer, "多普勒谱");
                    break;
                case IMAGE_1D:
                    parseDataBlock(buffer, "一维图像");
                    break;
                case DISTANCE_PULSE:
                    parseDistancePulseData(buffer);
                    break;
                case TIME_DOPPLER:
                    parseTimeDopplerSpectrumData(buffer);
                    break;
            }

            // 如果需要可视化，则调用可视化方法
            if (visualize) {
                visualize(type);
            }

            return parseResult;

        } catch (Exception e) {
            System.err.println("解析失败: " + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 跳过目标数据块之前的所有数据块
     * @param buffer 字节缓冲区
     * @param targetBlock 目标数据块
     */
    private void skipBlocksBeforeTarget(ByteBuffer buffer, BlockOrder targetBlock) {
        // 遍历所有数据块，跳过目标块之前的所有块
        for (BlockOrder block : BlockOrder.values()) {
            if (block == targetBlock) {
                // 已到达目标块，停止跳过
                break;
            }

            // 跳过当前块的所有字节
            skipBlock(buffer, block);
        }
    }

    /**
     * 跳过单个数据块的字节（根据块类型处理不同结构）
     */
    private void skipBlock(ByteBuffer buffer, BlockOrder block) {
        try {
            switch (block) {
                // 处理7个基础数据块（结构相同：int长度 + 2*N个double）
                case AVERAGE_SCATTERING:
                case TIME_VARYING_SCATTERING:
                case AMPLITUDE_PDF:
                case TIME_CORRELATION:
                case DISTANCE_CORRELATION:
                case DOPPLER_SPECTRUM:
                case IMAGE_1D:
                    int length = buffer.getInt();  // 读取长度（但不解析数据）
                    buffer.position(buffer.position() + 2 * length * 8);  // 跳过2*N个double（每个8字节）
                    break;

                // 处理距离-脉冲数据块
                case DISTANCE_PULSE:
                    int m = buffer.getInt();  // 距离门长度
                    buffer.position(buffer.position() + m * 8);  // 跳过距离门数据

                    int n = buffer.getInt();  // 脉冲数长度
                    buffer.position(buffer.position() + n * 8);  // 跳过脉冲数数据

                    // 跳过实部和虚部（各M*N个double）
                    buffer.position(buffer.position() + m * n * 8 * 2);
                    break;

                // 处理时变多普勒谱数据块
                case TIME_DOPPLER:
                    int p = buffer.getInt();  // 多普勒频率长度
                    buffer.position(buffer.position() + p * 8);  // 跳过频率数据

                    int q = buffer.getInt();  // 时间数据长度
                    buffer.position(buffer.position() + q * 8);  // 跳过时间数据

                    buffer.position(buffer.position() + p * q * 8);  // 跳过谱密度数据
                    break;
            }
        } catch (BufferUnderflowException e) {
            System.err.println("跳过数据块时发生异常（可能文件不完整）: " + block.name());
        }
    }


    /**
     * 解析数据块并存储到解析结果中
     *
     * @param buffer 包含数据块内容的字节缓冲区
     * @param blockName 数据块的名称标识
     */
    private void parseDataBlock(ByteBuffer buffer, String blockName) {
        DataBlock dataBlock = parseSingleDataBlock(buffer, blockName);
        parseResult.getDataBlocks().put(blockName, dataBlock);
    }


    /**
     * 解析单个数据块
     *
     * @param buffer 包含数据块信息的ByteBuffer对象
     * @param blockName 数据块名称
     * @return 解析后的DataBlock对象，包含数据块名称、长度和数据数组
     */
    private DataBlock parseSingleDataBlock(ByteBuffer buffer, String blockName) {
        try {
            // 读取数据块长度
            int length = buffer.getInt();
            List<Double> dataList = new ArrayList<>(2 * length);
            // 读取双精度浮点数数据到列表中
            for (int i = 0; i < 2 * length; i++) {
                dataList.add(buffer.getDouble());
            }

            // 将列表数据转换为数组
            double[] dataArray = new double[dataList.size()];
            for (int i = 0; i < dataList.size(); i++) {
                dataArray[i] = dataList.get(i);
            }

            System.out.printf("解析数据块: %s, 长度: %d, 数据量: %d%n",
                    blockName, length, dataArray.length);
            return new DataBlock(blockName, length, dataArray);

        } catch (BufferUnderflowException e) {
            System.out.printf("数据块 %s 解析中断（文件数据不足）%n", blockName);
            return new DataBlock(blockName, 0, new double[0]);
        }
    }


    /**
     * 解析距离-脉冲数据
     * <p>
     * 从ByteBuffer中读取距离-脉冲数据，包括距离门、脉冲、实部和虚部数据，
     * 并将其封装为DistancePulseData对象存储到parseResult中。
     *
     * @param buffer 包含距离-脉冲数据的ByteBuffer对象
     */
    private void parseDistancePulseData(ByteBuffer buffer) {
        try {
            // 读取距离门数量和脉冲数量
            int m = buffer.getInt();
            List<Double> rangeGates = new ArrayList<>(m);
            for (int i = 0; i < m; i++) {
                rangeGates.add(buffer.getDouble());
            }

            int n = buffer.getInt();
            List<Double> pulses = new ArrayList<>(n);
            for (int i = 0; i < n; i++) {
                pulses.add(buffer.getDouble());
            }

            // 读取复数数据的实部和虚部
            List<Double> realParts = new ArrayList<>(m * n);
            List<Double> imagParts = new ArrayList<>(m * n);
            for (int i = 0; i < m * n; i++) {
                realParts.add(buffer.getDouble());
            }
            for (int i = 0; i < m * n; i++) {
                imagParts.add(buffer.getDouble());
            }

            // 将List转换为数组并创建DistancePulseData对象
            double[] rangeGatesArr = listToDoubleArray(rangeGates);
            double[] pulsesArr = listToDoubleArray(pulses);
            double[][] realArr = listTo2DArray(realParts, n, m);
            double[][] imagArr = listTo2DArray(imagParts, n, m);

            parseResult.setDistancePulseData(new DistancePulseData(
                    rangeGatesArr, pulsesArr, realArr, imagArr
            ));
            System.out.printf("解析距离-脉冲数据: 距离门=%d, 脉冲数=%d%n", m, n);

        } catch (BufferUnderflowException e) {
            System.out.println("距离-脉冲数据解析中断（文件数据不足）");
            parseResult.setDistancePulseData(new DistancePulseData(
                    new double[0], new double[0], new double[0][0], new double[0][0]
            ));
        }
    }


    /**
     * 解析时变多普勒谱数据
     * 从ByteBuffer中读取时变多普勒谱数据，包括多普勒频率点、时间点和谱数据矩阵
     *
     * @param buffer 包含时变多普勒谱数据的字节缓冲区
     */
    private void parseTimeDopplerSpectrumData(ByteBuffer buffer) {
        try {
            // 读取多普勒频率点数量
            int p = buffer.getInt();
            List<Double> dopplerFreqs = new ArrayList<>(p);
            for (int i = 0; i < p; i++) {
                dopplerFreqs.add(buffer.getDouble());
            }

            // 读取时间点数量
            int q = buffer.getInt();
            List<Double> times = new ArrayList<>(q);
            for (int i = 0; i < q; i++) {
                times.add(buffer.getDouble());
            }

            // 读取谱数据
            List<Double> spectrumData = new ArrayList<>(p * q);
            for (int i = 0; i < p * q; i++) {
                spectrumData.add(buffer.getDouble());
            }

            // 转换数据格式并设置解析结果
            double[] dopplerArr = listToDoubleArray(dopplerFreqs);
            double[] timesArr = listToDoubleArray(times);
            double[][] spectrumArr = listTo2DArray(spectrumData, q, p);

            parseResult.setTimeDopplerSpectrum(new TimeDopplerSpectrum(
                    dopplerArr, timesArr, spectrumArr
            ));
            System.out.printf("解析时变多普勒谱: 频率点=%d, 时间点=%d%n", p, q);

        } catch (BufferUnderflowException e) {
            System.out.println("时变多普勒谱解析中断（文件数据不足）");
            parseResult.setTimeDopplerSpectrum(new TimeDopplerSpectrum(
                    new double[0], new double[0], new double[0][0]
            ));
        }
    }


    /**
     * 将Double类型的List转换为double数组
     * @param list 待转换的Double类型列表，不能为空
     * @return 转换后的double数组，数组长度与列表大小相同
     */
    private double[] listToDoubleArray(List<Double> list) {
        // 创建与列表大小相同的数组
        double[] arr = new double[list.size()];
        // 遍历列表，将每个元素复制到数组中
        for (int i = 0; i < list.size(); i++) {
            arr[i] = list.get(i);
        }
        return arr;
    }


    /**
     * 将一维列表转换为二维数组
     *
     * @param list 要转换的Double类型列表
     * @param rows 目标二维数组的行数
     * @param cols 目标二维数组的列数
     * @return 转换后的二维数组，如果列表元素不足则剩余位置为默认值0.0
     */
    private double[][] listTo2DArray(List<Double> list, int rows, int cols) {
        double[][] arr = new double[rows][cols];
        int index = 0;
        // 按行优先顺序填充二维数组
        for (int i = 0; i < rows && index < list.size(); i++) {
            for (int j = 0; j < cols && index < list.size(); j++) {
                arr[i][j] = list.get(index++);
            }
        }
        return arr;
    }


    /**
     * 根据指定的可视化类型进行数据可视化操作
     * @param type 可视化类型枚举值，决定要显示的数据类型
     */
    public void visualize(VisualizeType type) {
        // 检查数据是否已解析
        if (parseResult == null) {
            System.err.println("请先解析数据");
            return;
        }

        try {
            // 根据不同的可视化类型调用相应的可视化方法
            switch (type) {
                case AVERAGE_SCATTERING:
                    visualizeDataBlock("平均散射系数", "散射系数值");
                    break;
                case TIME_VARYING_SCATTERING:
                    visualizeDataBlock("时变散射系数", "时变散射值");
                    break;
                case AMPLITUDE_PDF:
                    visualizeDataBlock("幅度概率密度", "概率密度值");
                    break;
                case TIME_CORRELATION:
                    visualizeDataBlock("时间相关特性", "相关系数");
                    break;
                case DISTANCE_CORRELATION:
                    visualizeDataBlock("距离相关特性", "相关系数");
                    break;
                case DOPPLER_SPECTRUM:
                    visualizeDataBlock("多普勒谱", "功率谱密度");
                    break;
                case IMAGE_1D:
                    visualizeDataBlock("一维图像", "图像幅度");
                    break;
                case DISTANCE_PULSE:
                    visualizeDistancePulse(parseResult.getDistancePulseData());
                    break;
                case TIME_DOPPLER:
                    visualizeTimeDoppler(parseResult.getTimeDopplerSpectrum());
                    break;
            }
        } catch (Exception e) {
            System.err.println("可视化失败: " + e.getMessage());
            e.printStackTrace();
        }
    }


    /**
     * 可视化数据块
     *
     * @param blockName 数据块名称，用于从解析结果中获取对应的数据块
     * @param yAxisName Y轴标题，用于设置图表的Y轴显示名称
     */
    private void visualizeDataBlock(String blockName, String yAxisName) {
        // 获取指定名称的数据块
        DataBlock dataBlock = parseResult.getDataBlocks().get(blockName);
        // 检查数据块是否存在且数据量足够进行可视化
        if (dataBlock == null || dataBlock.getData().length < 2) {
            System.out.println(blockName + "数据不足，无法可视化");
            return;
        }

        // 将数据块中的数据分为x轴和y轴两部分
        int n = Math.min(dataBlock.getLength(), dataBlock.getData().length / 2);
        double[] x = Arrays.copyOfRange(dataBlock.getData(), 0, n);
        double[] y = Arrays.copyOfRange(dataBlock.getData(), n, Math.min(2 * n, dataBlock.getData().length));

        // 创建XY图表并设置基本属性
        XYChart chart = new XYChartBuilder()
                .width(800)
                .height(600)
                .title(blockName)
                .xAxisTitle("X轴")
                .yAxisTitle(yAxisName)
                .build();
        chart.getStyler().setLegendPosition(Styler.LegendPosition.InsideNW);
        chart.addSeries(blockName, x, y);

        // 显示图表
        new SwingWrapper<>(chart).displayChart();
    }


    /**
     * 添加数据提取方法，返回指定数据块的X和Y值
     * @param blockName 数据块名称
     * @return 包含X和Y值的Map，键为"X"和"Y"，值为对应的double数组
     */
    public Map<String, Object> extractDataPoints(String blockName) {
        Map<String, Object> result = new HashMap<>();

        // 检查数据块是否存在
        DataBlock dataBlock = parseResult != null ?
                parseResult.getDataBlocks().get(blockName) : null;

        if (dataBlock == null || dataBlock.getData().length < 2) {
            result.put("X", new double[0]);
            result.put("Y", new double[0]);
            return result;
        }

        // 提取X和Y数据
        int n = Math.min(dataBlock.getLength(), dataBlock.getData().length / 2);
        double[] x = Arrays.copyOfRange(dataBlock.getData(), 0, n);
        double[] y = Arrays.copyOfRange(dataBlock.getData(), n, Math.min(2 * n, dataBlock.getData().length));

        result.put("X", x);
        result.put("Y", y);
        return result;
    }


    /**
     * 根据可视化类型提取数据点
     *
     * @param type 可视化类型枚举值，用于指定要提取的数据类型
     * @return 返回包含数据点的Map，键为数据项名称，值为对应的数据对象
     */
    // 重载方法，支持通过VisualizeType提取数据
    public Map<String, Object> extractDataPoints(VisualizeType type) {
        String blockName;
        // 根据可视化类型转换为对应的块名称
        switch (type) {
            case AVERAGE_SCATTERING:
                blockName = "平均散射系数";
                break;
            case TIME_VARYING_SCATTERING:
                blockName = "时变散射系数";
                break;
            case AMPLITUDE_PDF:
                blockName = "幅度概率密度";
                break;
            case TIME_CORRELATION:
                blockName = "时间相关特性";
                break;
            case DISTANCE_CORRELATION:
                blockName = "距离相关特性";
                break;
            case DOPPLER_SPECTRUM:
                blockName = "多普勒谱";
                break;
            case IMAGE_1D:
                blockName = "一维图像";
                break;
            default:
                // 距离-脉冲和时变多普勒谱有特殊格式，这里暂不处理
                return new HashMap<>();
        }
        return extractDataPoints(blockName);
    }


    /**
     * 可视化一维图像
     *
     * @param imageBlock 包含一维图像数据的数据块对象
     */
    private void visualize1DImage(DataBlock imageBlock) {
        double[] data = imageBlock.getData();
        if (data.length < 2) {
            System.out.println("一维图像数据不足，无法可视化");
            return;
        }

        // 提取x轴和y轴数据，最多取前一半长度的数据
        int n = Math.min(imageBlock.getLength(), data.length / 2);
        double[] x = Arrays.copyOfRange(data, 0, n);
        double[] y = Arrays.copyOfRange(data, n, Math.min(2 * n, data.length));

        // 创建图表并设置基本属性
        XYChart chart = new XYChartBuilder()
                .width(800)
                .height(600)
                .title("一维图像")
                .xAxisTitle("位置")
                .yAxisTitle("幅度")
                .build();
        chart.getStyler().setLegendPosition(Styler.LegendPosition.InsideNW);
        chart.addSeries("一维图像数据", x, y);

        // 显示图表
        new SwingWrapper<>(chart).displayChart();
    }




    /**
     * 可视化距离-脉冲数据
     * @param data 距离-脉冲数据对象，包含距离门和实部信号数据
     */
    private void visualizeDistancePulse(DistancePulseData data) {
        double[] rangeGates = data.getRangeGates();
        double[][] real = data.getRealPart();
        // 检查数据是否足够进行可视化
        if (rangeGates.length == 0 || real.length == 0) {
            System.out.println("距离-脉冲数据不足，无法可视化");
            return;
        }

        // 限制显示的脉冲数量，最多显示5个
        int displayCount = Math.min(5, real.length);
        // 创建图表对象并设置基本属性
        XYChart chart = new XYChartBuilder()
                .width(800)
                .height(600)
                .title("距离-脉冲数据")
                .xAxisTitle("距离门")
                .yAxisTitle("信号强度")
                .build();
        chart.getStyler().setLegendPosition(Styler.LegendPosition.InsideNW);

        // 为每个脉冲数据添加图表系列
        for (int i = 0; i < displayCount; i++) {
            chart.addSeries("脉冲 " + (i + 1), rangeGates, real[i]);
        }

        // 显示图表
        new SwingWrapper<>(chart).displayChart();
    }


    /**
     * 提取指定序号的距离-脉冲数据（序号从1开始，null则返回第一条）
     *
     * @param index 指定的序号，从1开始计数，如果为null则返回第一条数据
     * @return MultiCurveDataDTO对象，包含X轴距离门数据、Y轴指定脉冲的实部数据、总脉冲数和当前序号
     */
    public MultiCurveDataDTO getDistancePulseByIndex(Integer index) {
        DistancePulseData data = parseResult != null ? parseResult.getDistancePulseData() : null;
        if (data == null) {
            return new MultiCurveDataDTO(new double[0], new double[0], 0, 0);
        }

        double[] xAxis = data.getRangeGates(); // X轴共用（距离门）
        double[][] yDataList = data.getRealPart(); // Y轴数据列表（各脉冲的实部）
        int totalCount = yDataList.length;

        // 处理序号：null则默认1，超出范围则取最后一条
        int currentIndex = (index == null || index < 1) ? 1 :
                (index > totalCount ? totalCount : index);

        // 转换为0基索引并获取对应Y轴数据
        int arrayIndex = currentIndex - 1;
        double[] yAxis = (arrayIndex >= 0 && arrayIndex < yDataList.length)
                ? yDataList[arrayIndex]
                : new double[0];

        return new MultiCurveDataDTO(xAxis, yAxis, totalCount, currentIndex);
    }

    /**
     * 可视化时变多普勒谱
     * @param data 时变多普勒谱数据对象，包含频率信息和谱密度信息
     */
    private void visualizeTimeDoppler(TimeDopplerSpectrum data) {
        double[] doppler = data.getDopplerFrequencies();
        double[][] spectrum = data.getSpectrumDensity();
        // 检查数据是否充足
        if (doppler.length == 0 || spectrum.length == 0) {
            System.out.println("时变多普勒谱数据不足，无法可视化");
            return;
        }

        // 限制显示的时间点数量，最多显示5个
        int displayCount = Math.min(5, spectrum.length);
        XYChart chart = new XYChartBuilder()
                .width(800)
                .height(600)
                .title("时变多普勒谱")
                .xAxisTitle("频率 (Hz)")
                .yAxisTitle("谱密度")
                .build();
        chart.getStyler().setLegendPosition(Styler.LegendPosition.InsideNW);

        // 为每个时间点添加数据系列到图表中
        for (int i = 0; i < displayCount; i++) {
            chart.addSeries("时间点 " + i, doppler, spectrum[i]);
        }

        // 显示图表
        new SwingWrapper<>(chart).displayChart();
    }


    /**
     * 提取指定序号的时变多普勒谱数据（序号从1开始，null则返回第一条）
     *
     * @param index 指定的序号，从1开始计数，如果为null则返回第一条数据
     * @return MultiCurveDataDTO对象，包含X轴频率数据、Y轴谱密度数据、总数据条数和当前序号
     */
    public MultiCurveDataDTO getTimeDopplerByIndex(Integer index) {
        TimeDopplerSpectrum data = parseResult != null ? parseResult.getTimeDopplerSpectrum() : null;
        if (data == null) {
            return new MultiCurveDataDTO(new double[0], new double[0], 0, 0);
        }

        double[] xAxis = data.getDopplerFrequencies(); // X轴共用（频率）
        double[][] yDataList = data.getSpectrumDensity(); // Y轴数据列表（各时间点的谱密度）
        int totalCount = yDataList.length;

        // 处理序号：null则默认1，超出范围则取最后一条
        int currentIndex = (index == null || index < 1) ? 1 :
                (index > totalCount ? totalCount : index);

        // 转换为0基索引并获取对应Y轴数据
        int arrayIndex = currentIndex - 1;
        double[] yAxis = (arrayIndex >= 0 && arrayIndex < yDataList.length)
                ? yDataList[arrayIndex]
                : new double[0];

        return new MultiCurveDataDTO(xAxis, yAxis, totalCount, currentIndex);
    }





    /**
     * 提取基础数据块DTO（X-Y格式）
     */
    public BasicDataDTO getBasicDataDTO(VisualizeType type) {
        String blockName = getBlockNameByType(type);
        DataBlock dataBlock = parseResult != null ? parseResult.getDataBlocks().get(blockName) : null;
        return BasicDataDTO.fromDataBlock(dataBlock);
    }

    /**
     * 提取距离-脉冲数据DTO
     */
    public DistancePulseDTO getDistancePulseDTO() {
        DistancePulseData data = parseResult != null ? parseResult.getDistancePulseData() : null;
        return DistancePulseDTO.fromEntity(data);
    }

    /**
     * 提取时变多普勒谱DTO
     */
    public TimeDopplerDTO getTimeDopplerDTO() {
        TimeDopplerSpectrum data = parseResult != null ? parseResult.getTimeDopplerSpectrum() : null;
        return TimeDopplerDTO.fromEntity(data);
    }

    /**
     * 根据类型获取数据块名称
     */
    private String getBlockNameByType(VisualizeType type) {
        switch (type) {
            case AVERAGE_SCATTERING: return "平均散射系数";
            case TIME_VARYING_SCATTERING: return "时变散射系数";
            case AMPLITUDE_PDF: return "幅度概率密度";
            case TIME_CORRELATION: return "时间相关特性";
            case DISTANCE_CORRELATION: return "距离相关特性";
            case DOPPLER_SPECTRUM: return "多普勒谱";
            case IMAGE_1D: return "一维图像";
            default: throw new IllegalArgumentException("不支持的基础数据类型: " + type);
        }
    }
    /**
     * 测试方法
     */
    public static void main(String[] args) {
        String filePath = "D:\\项目\\环境预览\\【内部】BIN\\【内部】20240612110719_YS_SS2_CW_Ku_HH_5_SeaEMData.bin";

        // 1. 实例化工具类
        ElectromagneticDataTool tool = new ElectromagneticDataTool(filePath);

        // 2. 解析数据（自动检测字节序，可视化）
        // 可通过指定类型只展示单个图表，避免内存溢出
        ParseResult result = tool.parse(true, ElectromagneticDataTool.VisualizeType.AVERAGE_SCATTERING  );

        // 3. 处理结果
        if (result != null) {
            System.out.println("解析完成，数据块数量: " + result.getDataBlocks().size());
        }
    }
}